package cn.touna.jss.modules.adapter;

import cn.touna.jss.common.entity.CreditQueryRequest;
import cn.touna.jss.common.entity.FileRequestEntity;
import cn.touna.jss.common.factory.ResponseFactory;
import cn.touna.jss.common.util.CommonUtils;
import cn.touna.risk.api.domain.Response;
import cn.touna.risk.api.entity.RequestEntity;
import cn.touna.risk.api.enums.SystemErrorCodeEnum;
import cn.touna.risk.api.exception.BusinessException;
import cn.touna.risk.api.exception.ServiceException;
import cn.touna.risk.api.utils.IntfTypeUtil;
import cn.touna.risk.api.utils.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.touna.loan.log.service.TracerContextUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

/**
 * Api 工具类
 *
 * @Author:wuwc
 * @Description:
 * @Date:2018/3/2 15:27
 */
public class ApiUtils {

    private static final Logger logger = LogManager.getLogger(ApiUtils.class);

    /**
     * 兼容老版本方式，生成接口名称
     *
     * @param requestEntity
     * @return
     * @throws ServiceException
     */
    public static String genApiMethod(RequestEntity requestEntity) throws ServiceException {

        if (StringUtils.isNotBlank(requestEntity.getMethod())) {
            return requestEntity.getMethod();
        } else {
            String serviceName = requestEntity.getServiceName();
            String methodName = requestEntity.getMethodName();
            return validateSysParam(serviceName, methodName);
        }
    }


    /**
     * 校验公共参数
     *
     * @param serviceName
     * @param methodName
     * @return
     * @throws ServiceException
     */
    public static String validateSysParam(String serviceName, String methodName) throws ServiceException {

        if (StringUtils.isAnyBlank(serviceName, methodName)) {
            throw new ServiceException("接口名称不能为空！");
        }
        StringBuilder methodBuilder = new StringBuilder();
        return methodBuilder.append(serviceName).append(".").append(methodName).toString();
    }

    /**
     * 异常处理
     *
     * @param e
     * @param method
     * @param <T>
     * @return
     */
    public static <T> Response handError(Throwable e, String method) {
        Response response = new Response();
        if (BusinessException.class.isAssignableFrom(e.getClass())) {
            //业务参数异常，属于已知可控的异常，已经告知客户端，不用在ERROR log中打印
            //logger.error("REE【业务参数异常】,mehtod:{},msg:{}", method, e);
            return new Response().fail(SystemErrorCodeEnum.JSS_PARAM_CHECK_FAILED.getErrorCode(), e.getMessage());
        }
        if (ServiceException.class.isAssignableFrom(e.getClass())) {
            logger.error("REE【服务异常】,mehtod:{},msg:{}", method, e);
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_SERVICE_CHECK_ERROR, e.getMessage());
        }

        if (e.getCause() != null && ConstraintViolationException.class.isAssignableFrom(e.getCause().getClass())) {
            Set<ConstraintViolation<?>> constraintViolations = ((ConstraintViolationException) e.getCause()).getConstraintViolations();
            Iterator<ConstraintViolation<?>> iterable = constraintViolations.iterator();
            String message = "";
            while (iterable.hasNext()) {
                message = iterable.next().getMessageTemplate();
            }
            logger.error("REE【参数校验异常】,mehtod:{},msg:{}", method, message);
            return response.fail(SystemErrorCodeEnum.JSS_PARAM_CHECK_FAILED.getErrorCode(), message);
        }
        if (Exception.class.isAssignableFrom(e.getClass())) {
            String message = CommonUtils.getErrorMessage(e);
            logger.error("REE【系统异常】,mehtod:{},message:{}", method, message);
            return response.fail(SystemErrorCodeEnum.JSS_SYSTEM_ERROR, message);
        }
        logger.error("REE【系统异常】,mehtod:{},error:{}", method, e);
        return response.fail(SystemErrorCodeEnum.JSS_SYSTEM_ERROR);
    }

    /**
     * 将MAP转换成具体的目标方方法参数对象
     *
     * @param val
     * @param targetClass
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> Object convertJsonToBean(Object val, Class<T> targetClass) throws Exception {
        Object result = null;
        if (val == null) {
            return null;
        } else if (Integer.class.isAssignableFrom(targetClass)) {
            result = Integer.parseInt(val.toString());
        } else if (Long.class.isAssignableFrom(targetClass)) {
            result = Long.parseLong(val.toString());
        } else if (Date.class.isAssignableFrom(targetClass)) {
            if (val.toString().matches("[0-9]+")) {
                result = new Date(Long.parseLong(val.toString()));
            } else {
                throw new IllegalArgumentException("日期必须是长整型的时间戳");
            }
        } else if (String.class.isAssignableFrom(targetClass)) {
            if (val instanceof String) {
                result = val;
            } else {
                throw new IllegalArgumentException("转换目标类型为字符串");
            }
        } else {
            result = JSONUtil.convertValue(val, targetClass);
        }
        return result;
    }

    public static Response hanldReturnResult(Object result) {
        try {
            if (result == null) {
                return ResponseFactory.fail(SystemErrorCodeEnum.JSS_SYSTEM_ERROR);
            }
            if (result instanceof Response) {
                return (Response) result;
            }
            return ResponseFactory.success(result);
        } catch (Exception e) {
            logger.error("服务中心响应异常", e);
            throw new RuntimeException(e);
        }
    }

    public static CreditQueryRequest assembleQueryRequest(String apiMethod, RequestEntity requestEntity) {
        CreditQueryRequest queryRequest = new CreditQueryRequest();
        try {
            queryRequest.setCrNo(TracerContextUtil.getTraceId());
            queryRequest.setBizType(requestEntity.getBizType());
            queryRequest.setQueryTime(new Date());
            queryRequest.setServiceName(IntfTypeUtil.splitIntfType(apiMethod)[0]);
            queryRequest.setMethodName(IntfTypeUtil.splitIntfType(apiMethod)[1]);
            queryRequest.setMethod(apiMethod);
            queryRequest.setParams(requestEntity.getParams());
            queryRequest.setIdCard(JSONUtil.getString(requestEntity.getParams(), "idCard", null));
            queryRequest.setMobile(JSONUtil.getString(requestEntity.getParams(), "mobile", null));
            queryRequest.setClientIp(requestEntity.getClientIp());
        } catch (Exception e) {
            logger.error("初始化请求参数失败，msg:{}", e.getMessage());
        }
        return queryRequest;
    }

    public static CreditQueryRequest assembleFileRequest(FileRequestEntity fileRequestEntity) {
        CreditQueryRequest queryRequest = new CreditQueryRequest();
        try {
            String apiMethod = ApiUtils.genApiMethod(fileRequestEntity);
            queryRequest.setCrNo(TracerContextUtil.getTraceId());
            queryRequest.setBizType(fileRequestEntity.getBizType());
            queryRequest.setSysName(fileRequestEntity.getSysName());
            queryRequest.setProductType(fileRequestEntity.getProductType());
            queryRequest.setPhaseName(fileRequestEntity.getPhaseName());
            queryRequest.setQueryTime(new Date());
            queryRequest.setServiceName(IntfTypeUtil.splitIntfType(apiMethod)[0]);
            queryRequest.setMethodName(IntfTypeUtil.splitIntfType(apiMethod)[1]);
            queryRequest.setMethod(apiMethod);
            JSONObject params = JSONUtil.getJSONObject(fileRequestEntity.getBizContent());
            queryRequest.setParams(params);
            queryRequest.setIdCard(JSONUtil.getString(params, "idCard", null));
            queryRequest.setMobile(JSONUtil.getString(params, "mobile", null));
            queryRequest.setClientIp(fileRequestEntity.getClientIp());
        } catch (ServiceException e) {
            logger.error("初始化请求参数失败，msg:{}", e.getMessage());
        }
        return queryRequest;
    }
}
